﻿using System;
using System.Linq;
using System.Runtime.Serialization;
using BrainTechLLC.Communication;
using BrainTechLLC;
using System.Net;
using BrainTechLLC.ThreadSafeObjects;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;
using UserInterface;
using System.Collections.ObjectModel;
using System.IO;
using Mud.EmlenMudMain;

namespace BrainTechLLC.Silverlight.ClientApplication.Web
{
    public partial class DataService
    {
        [OperationContract, FaultContract(typeof(Fault))]
        public List<GameChar> ReadAllGameCharacters(int uniqueId, UsernamePassword usernamePassword)
        {
            var results = WithFaultSupport(() => Everything.FindAllThingsOfType<GameChar>());
            return results;
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<GameCharTemplate> ReadAllGameCharacterTemplates(int uniqueId, UsernamePassword usernamePassword)
        {
            var results = WithFaultSupport(() => Everything.FindAllThingsOfType<GameCharTemplate>());
            return results;
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<ItemTemplate> ReadAllItemTemplates(int uniqueId, UsernamePassword usernamePassword)
        {
            var results = WithFaultSupport(() => Everything.FindAllThingsOfType<ItemTemplate>());
            return results;
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<Area> ReadAllAreas(int uniqueId, UsernamePassword usernamePassword)
        {
            return WithFaultSupport(() => Everything.FindAllThingsOfType<Area>());
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<GameChar> ReadGameCharacters(int uniqueId, UsernamePassword usernamePassword)
        {
            try
            {
                UsernamePassword found = UsernamesPasswords.Instance.DoLogin(usernamePassword);

                if (found == null)
                    return null;

                found.UniqueConnectionId = uniqueId;

                if (found.AssociatedIDs == null)
                    return new List<GameChar>();

                return Everything.Find<GameChar>(found.AssociatedIDs.AllItems);
            }
            catch (Exception e)
            {
                throw new FaultException<Fault>(new Fault(e.ToString()));
            }
        }

        // HEREHERE
        [OperationContract, FaultContract(typeof(Fault))]
        public List<Method> ReadStaticMethods(int uniqueId)
        {
            List<Method> result = new List<Method>();
            List<Type> types = TypeProvider.GetInstance()._typeLookup.AllItems;
            for (int n = 0; n < types.Count; n++)
            {
                Type t = types[n];
                var methods = t.GetMethods(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.IgnoreCase);
                for (int i = 0; i < methods.Length; i++)
                {
                    MethodVisible[] vis = methods[i].ReadAttribute<MethodVisible>();
                    if (vis != null && vis.Length > 0 && vis[0].Val)
                    {
                        var method = new Method(t.FullName, methods[i].Name);
                        result.Add(method);
                    }
                }
            }

            return result;
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<GameLocation> ReadWorldMap()
        {
            List<GameLocation> locs = WithFaultSupport<List<GameLocation>>(() => WorldMap.Instance.World.AllItems);

            return locs;
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<LocationEdge> ReadLocationEdges()
        {
            try
            {
                List<LocationEdge> locs = Everything.FindAllThingsOfType<LocationEdge>();
                return locs;
            }
            catch (Exception e)
            {
                GlobalLogger.Log(e, LogSeverity.Critical, true);
                throw new FaultException<Fault>(new Fault(e.ToString()));
            }
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public GameChar ReadGameChar(int uniqueId, long id)
        {
            return WithFaultSupport(() => Read<GameChar>(id));
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public BytesAndType ReadById(int uniqueId, long id)
        {
            GameThingBaseClass thing = Everything.Find<GameThingBaseClass>(id);

            if (thing == null)
                return null;

            DataContractSerializer s = new DataContractSerializer(thing.GetType());
            BytesAndType result = new BytesAndType();

            using (MemoryStream ms = new MemoryStream())
            {
                s.WriteObject(ms, thing);
                result.Bytes = Encoding.UTF8.GetString(ms.ToArray());
                result.Type = thing.GetType().Name;
            }

            return result;
        }


        [OperationContract, FaultContract(typeof(Fault))]
        public List<Ability> LoadAbilitiesFromIds(List<long> ids)
        {
            return WithFaultSupport(() => Everything.Find<Ability>(ids));
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<State> LoadStatesFromIds(List<long> ids)
        {
            return WithFaultSupport(() => Everything.Find<State>(ids));
        }

        [OperationContract, FaultContract(typeof(Fault))]
        public List<Channel> LoadChannels()
        {
            return WithFaultSupport(() => Everything.FindAllThingsOfType<Channel>());
        }

        public T Read<T>(long id) where T : class, IGameThing
        {
            return Everything.Find<T>(id);
        }
    }
}
